/**
 * \file radio.c
 * \brief Implémentation des taches de l'OS
 * \author Nicolas.M
 * \version 0.1
 * \date 11 septembre 2007
 *
 * Fichier d'implémentation des taches appeler par l'OS.
 *
 */
 
 #include "radio.h"

#include "driver/lcd.h"
#include "driver/frequence.h"
#include "driver/volume.h"
#include "driver/led.h"
#include "driver/irda.h"


#include "control/ctrl_mem.h"


#include "mode/menu.h"
#include "mode/stats.h"
#include "mode/simon.h"

#include "utils/resources.h"
#include "utils/utils.h"
#include "utils/display.h"

#include <msp430x14x.h>
#include <includes.h>

#define SEM_SUPER_PRIORITY 9

typedef void (*fp)(void);

extern OS_EVENT *SemBus;

extern OS_EVENT *BipMbox;
extern OS_EVENT *DisplayMbox;
extern OS_EVENT *ButtonMbox;
extern OS_EVENT *StatsMbox;

extern void *DisplayMboxData[];

void initRessource()
{
	INT8U err;
	// Creation des ressources partagees
	SemBus = OSMutexCreate(9, &err);

	BipMbox = OSMboxCreate((void *)0);
	ButtonMbox = OSMboxCreate((void *)0);
	StatsMbox = OSMboxCreate((void *)0);
	DisplayMbox = OSQCreate(&DisplayMboxData[0], 16);

}

/**********************************************************************************
 * 				definition des taches de test
 * ********************************************************************************/
 
 
 // tache de test de l'affichage
void testDisplay(void* pdata)  
{
	INT8U err;
	pdata = pdata;
	TACTL |= MC1;           /* Start the Timer in Continuous mode. */
	initDisplay();
	printDisplay("Hello\n World !!!"); // test l'affichage d'une chaine
	OSMboxPend(ButtonMbox, 0, &err);
	clearDisplay();	// test l'effacement de l'affichage
	OSMboxPend(ButtonMbox, 0, &err);
	printDisplay("Display cleared, depassement"); // test le dépassement sur la fonction printDisplay 
	OSMboxPend(ButtonMbox, 0, &err);
	printDisplay("Display cleared, depassement \n test ligne 3"); // test le dépassement sur la fonction printDisplay 
	OSMboxPend(ButtonMbox, 0, &err);
	clearDisplay();
	lprintDisplay("ligne 1", FIRST_LINE);	//test l'affichage sur la ligne 1
	OSMboxPend(ButtonMbox, 0, &err);
	lprintDisplay("ligne 2", SECOND_LINE);	//test l'affichage sur la ligne 2
	OSMboxPend(ButtonMbox, 0, &err);
	clearDisplay();
	lprintDisplay("depassement 1, tronquature", FIRST_LINE);	// test le dépassement sur la ligne 1
	OSMboxPend(ButtonMbox, 0, &err);
	lprintDisplay("depassement 2, tronquature", SECOND_LINE);	// test le dépassement sur la ligne 2
	OSMboxPend(ButtonMbox, 0, &err);
	cprintDisplay('5', FIRST_LINE, 4);	// test la fonction cprintDisplay
	OSMboxPend(ButtonMbox, 0, &err);
	putcDisplay('8');	// test la fonction putcDisplay
	OSMboxPend(ButtonMbox, 0, &err);
	clearDisplay();
	OSMboxPend(ButtonMbox, 0, &err);
	clearDisplay();
	OSMboxPend(ButtonMbox, 0, &err);
	while(1){};
	
}
	
void testLED(void* pdata)  
{
	INT8U err;
	pdata = pdata;
	TACTL |= MC1;           /* Start the Timer in Continuous mode. */
	initLedBar();

	OSMboxPend(ButtonMbox, 0, &err);
	SEL_ON;
	OSMboxPend(ButtonMbox, 0, &err);
	SEL_ON;
	OSMboxPend(ButtonMbox, 0, &err);
	SEL_OFF;
	OSMboxPend(ButtonMbox, 0, &err);
	D_ON;
	OSMboxPend(ButtonMbox, 0, &err);
	D_OFF;
	OSMboxPend(ButtonMbox, 0, &err);
	D_ON;
	OSMboxPend(ButtonMbox, 0, &err);
	SEL_ON;
	OSMboxPend(ButtonMbox, 0, &err);
	D_OFF;

	OSMboxPend(ButtonMbox, 0, &err);
	allumerLedBar(3);
	OSMboxPend(ButtonMbox, 0, &err);
	barTousEteindre();
	OSMboxPend(ButtonMbox, 0, &err);
	barAllumerNiveau(5);
	OSMboxPend(ButtonMbox, 0, &err);
	barAllumerNiveau(5);
	OSMboxPend(ButtonMbox, 0, &err);
	eteindreLedBar(2);
	OSMboxPend(ButtonMbox, 0, &err);
	eteindreLedBar(2);
	OSMboxPend(ButtonMbox, 0, &err);
	barTousEteindre();
	OSMboxPend(ButtonMbox, 0, &err);
	barTousAllumer();
	OSMboxPend(ButtonMbox, 0, &err);
	while(1){}
}	
	
void testFreq(void* pdata)
{
	INT8U err;
	pdata = pdata;
	TACTL |= MC1;
	setVolume(2);
	OSMboxPend(ButtonMbox, 0, &err);
	setFrequence(218); //Lyon 1ere
	OSMboxPend(ButtonMbox, 0, &err);
	setFrequence(504); //Virgin
	OSMboxPend(ButtonMbox, 0, &err);
	setFrequence(504); //Virgin
	OSMboxPend(ButtonMbox, 0, &err);
	while(1){}
}

void testVolume(void* pdata)
{
	INT8U err;
	pdata = pdata;
	TACTL |= MC1;
	setFrequence(504);
	OSMboxPend(ButtonMbox, 0, &err);
	setVolume(0); 
	OSMboxPend(ButtonMbox, 0, &err);
	setVolume(0); 
	OSMboxPend(ButtonMbox, 0, &err);
	setVolume(2); 
	OSMboxPend(ButtonMbox, 0, &err);
	setVolume(2); 
	OSMboxPend(ButtonMbox, 0, &err);
	mute() ;
	OSMboxPend(ButtonMbox, 0, &err);
	mute();
	OSMboxPend(ButtonMbox, 0, &err);
	while(1){}
}

void testMem(void *pdata)
{
	int timer = 0;
	int currentVolume = 3;
	int currentStation = 2;
	int currentFrequence = 100;
	char *info,*nb;
	initDisplay();
	
	info = malloc(32*sizeof(char));
	nb = malloc(3*sizeof(char));
	initMemory();
	razMemory();
	resetMemory();
	saveStationPerso(currentStation,currentFrequence);
	while (1)
	{
		*info = 0;
		clearDisplay();
		augmenterStationTimeStat(currentStation,5);
		augmenterVolTimeStat (currentVolume,10);
		augmenterVolTimeStat (7,8);
		itoa(getStationPerso(2),nb,10);
		info = strcat(info, nb);
		info = strcat(info,"   time: ");
		itoa(getStationTimeStat(currentStation),nb,10);
		info = strcat(info,nb);
		printDisplay(info);
		OSTimeDly(50);
	}

}

 // tache de test de l'affichage
void testDisplayTask(void* pdata)  
{
	INT8U err;
	pdata = pdata;
	TACTL |= MC1;           /* Start the Timer in Continuous mode. */
	OSMboxPend(ButtonMbox, 0, &err);
	afficher("Hello\n World !!!"); // test l'affichage d'une chaine
	OSMboxPend(ButtonMbox, 0, &err);
	clearDisplay();	// test l'effacement de l'affichage
	OSMboxPend(ButtonMbox, 0, &err);
	afficherChar('V', 1, 3);
	OSMboxPend(ButtonMbox, 0, &err);
	afficherChar('V', 0, 2);
	OSMboxPend(ButtonMbox, 0, &err);
	afficherChar('V', 1, 10); 
	OSMboxPend(ButtonMbox, 0, &err);
	while(1){}
	
}
/**********************************************************************************
 * 				definition des taches 
 * ********************************************************************************/
 

void restaurerContexte()
{
	int i = 0;
	// User Stations
	while (i<5)
	{
		restaurerUserStation(i+1, getStationPerso(i+1));
		i++;
	}
	// Mode
	restaurerMode(getSavedMode());
	// Volume
	restaurerVolume(getSavedVol());
	// Frequence
	restaurerFrequence(getSavedFreq());
	// Station
	restaurerStation(getSavedStation());
}

void start(void* pdata)
{
	pdata = pdata;
	int button;
	INT8U err;
	
	TACTL |= MC1; //Lancement du timer A afin de générer le TICKTIME de l'OS
	
	irdaInit();
	//Restauration de la memoire
	initMemory();
	
	while (1)
	{
		afficher("");
		OSTimeDly(DELAY_100ms*3);
		LPM3;  // Mise en veille de niveau 3 : reste seulement l'horloge ACLK pour le reveiol avec la télé.
		button = OSMboxPend(ButtonMbox, 0, &err); // Choix du mode au démarrage
		if (err == OS_NO_ERR)
		{
			switch (button)
			{
				case COM_PLAY:
					if(!OSMboxPend(ButtonMbox, DELAY_100ms*2, &err)) break;  
				case COM_B1_LONG:
					restaurerContexte();
					hook();
					break;

				case COM_B2_LONG:
					consultStats();
					break;

				case COM_B3_LONG:
					simon();
					break;
			}
		}
	}
}

void display(void* pdata)
{
	pdata = pdata;
	INT8U err;
	DisplayCommand *chaine;
	initDisplay();
	while(1)
	{
		chaine = OSQPend(DisplayMbox, 0, &err);
		if (err == OS_NO_ERR)
		{
			affichage(chaine);
			free(chaine);
		}
	}
}


void majStats(void* pdata)
{
	static int LED=0;
	int err, on, val;
	pdata = pdata;
	
	/*
	 * La tache de stats se suspend elle meme
	 * dès le debut parce qu'elle ignore le contexte
	 * de l'application. C'est le menu qui la réveillera
	 * quand ce sera necessaire.
	 */
	while(1)
	{
		OSTimeDly(DELAY_1sec);
		if(isMenuRunning() && getFMMode() == MODE_STATION)
		{
			if (LED==1)
			{
				LED=0;
				P2OUT &= ~BIT1;
			}
			else if(LED==0)
			{
				LED=1;
				P2OUT |= BIT1 ;
			}
			updateStats();
		}
	}
}

void buttonBipper(void *pdata)
{
	pdata = pdata;
	int debut;
	INT8U err;
	while (1)
	{
		if (OSMboxPend(BipMbox, 0, &err) == DO_BIP)
		{
			OSMboxPend(BipMbox, DELAY_100ms*5, &err);
			if (err == OS_TIMEOUT)
			{	
				debut = OSTimeGet();
				while (OSTimeGet()-debut<7) 
				{
					P4OUT |= BIT3;
					delayx100us(3);
					P4OUT &= ~BIT3;
					delayx100us(1);
				}
			}
		}
	}
}



